#!/usr/bin/env python3

# Copyright (c) 2020-2021 Fpemud <fpemud@sina.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import os
import pwd
import hashlib
from ..._util import Util, CopiedAndSymlinkedDir
from ..._errors import DataDirError, ConfigError, RunnerError
from ..._game import GameBase, GameSpec, MatchContext, GameSupportIconDir
from ..._game_straits import GameStraitForWindows, GameStraitNeedConfigDir


class NeedForSpeed8(GameBase, GameStraitForWindows, GameSupportIconDir):

    class LevelOfDetail:

        def __init__(self):
            self.CarEnvironmentMapEnable = None             # int: 0 - 3
            self.CarEnvironmentMapUpdateData = None         # int: 0 - 1
            self.CarLodLevel = None                         # int: 0 - 1
            self.FSAALevel = None                           # int: 0 - 3
            self.MotionBlurEnable = None                    # bool
            self.OverBrightEnable = None                    # bool
            self.ParticleSystemEnable = None                # bool
            self.PerformanceLevel = None                    # int: 0 - 5
            self.RainEnable = None                          # bool
            self.RoadReflectionEnable = None                # bool
            self.ShadowDetail = None                        # int: 0 - 2
            self.TextureFiltering = None                    # int: 0 - 2
            self.VisualTreatment = None                     # int: 0 - 1
            self.VSyncOn = None                             # bool
            self.WorldLodLevel = None                       # int: 0 - 3

        def __eq__(self, other):
            return self.__class__ == other.__class__ and self.__dict__.values() == other.__dict__.values()

        def __ne__(self, other):
            return not self.__eq__(other)

    def __init__(self, data_dir):
        GameBase.__init__(self, data_dir)
        GameSupportIconDir.__init__(self, os.path.join(self._dataDir, "icons"))

        self._addStrait(GameStraitNeedConfigDir())

        # directories and files
        # self._gameDir = os.path.join(self._dataDir, "Need For Speed Most Wanted")
        # self._gameLangDir = os.path.join(self._dataDir, "language-pack")

        # spec
        self._spec = GameSpec()
        self._resolutionToNumberDict = {
            "640x480": 1,
            "800x600": 2,
            "1024x768": 3,
            "1280x960": 4,
            "1600x1200": 5,
        }
        self._numberToResolutionDict = {
            0: "640x480",
            1: "640x480",
            2: "800x600",
            3: "1024x768",
            4: "1280x960",
            5: "1600x1200",
        }
        if True:
            self._spec.windows_archs = [self.WindowsArch.WIN32]
            self._spec.windows_versions = [self.WindowsVersion.WINXP, "*"]

            self._spec.default_language = "en_US"
            self._spec.languages = [self._spec.default_language]

            self._spec.resolutions = list(self._resolutionToNumberDict.keys())

            self._spec.can_fullscreen = True
            self._spec.can_windowed = False

            self._spec.graphics_api = ["directx9"]

        self._lowestResolution = "640x480"
        self._highestResolution = "1600x1200"
        self._lowestResolutionId = 1
        self._highestResolutionId = 5

        # self._keyName = "HKEY_LOCAL_MACHINE\\Software\\EA GAMES\\Need For Speed Most Wanted"

    @property
    def spec(self):
        return self._spec

    @property
    def run_items(self):
        return ["main"]

    def get_title(self, lang):
        return "Need For Speed Underground 2"

    def _prepare(self, context):
        self._context = context
        try:
            self._username = pwd.getpwuid(os.geteuid()).pw_name
            self._targetCfgDir = os.path.join(self._context.drive_c_dirpath, "users", self._username, "Documents")

            # create game files, including language pack files
            self._targetGameDirObj = CopiedAndSymlinkedDir(os.path.join(self._context.drive_c_dirpath, "game"), [self._dataDir])
            self._targetGameDirObj.symlink("", recursive=True)

            # create registry keys, including language related keys
            # windows_registry.import_file(os.path.join(self._gameLangDir, self._curLang + ".reg"))

            # copy config files
            # Util.forceCopy(os.path.join(config.dir_path, "NFS Most Wanted"), os.path.join(targetCfgDir, "NFS Most Wanted"))

            # apply config
            # self._writeResolutionToRegistry(windows_registry, self._readResolutionFromGameIni(config.game_ini))
            # self._writeLevelOfDetailToRegistry(windows_registry, self._readLevelOfDetailFromGameIni(config.game_ini))
        except BaseException:
            self._cleanup(on_error=True)
            raise

    @MatchContext.edit_or_run
    def get_language(self):
        assert False

    @MatchContext.edit_or_run
    def set_language(self, language):
        pass

    @MatchContext.run
    def apply_resolution(self, resolution):
        pass

    @MatchContext.run
    def apply_fullscreen_or_windowed(self, fullscreen_or_windowed):
        assert fullscreen_or_windowed

    def _commit(self):
        pass

    def _getRunInfo(self, item):
        assert not self._context.edit_or_run
        assert item == Util.listGetOnlyItem(self.run_items)

        return self.RunInfo("C:\\game\\SPEED2.EXE")

    def _cleanup(self, on_error=False):
        if hasattr(self, "_targetGameDirObj"):
            if not on_error:
                # copy config files
                # Util.forceCopy(os.path.join(self._targetCfgDir, "NFS Most Wanted"), os.path.join(self._context.config_dirpath, "NFS Most Wanted"))
                pass
            self._targetGameDirObj.dispose()
            del self._targetGameDirObj
        if hasattr(self, "_context"):
            del self._context


class SaveFile:

    # from https://github.com/BilawalAhmed0900/NFSU2SaveE
    # from https://github.com/ram-on/nfsu2-money-cheat

    class Car:

        def __init__(self):
            self.is_sold = False
            self.id = None
            self.bounty = None

    class ParseError(Exception):
        pass

    def __init__(self, parent, filename, path):
        self._parent = parent
        self._filename = filename
        self._path = path

        self._account = None
        self._money = None
        self._carList = []
        with open(self._path, "rb+") as inptr:
            if inptr.read(4) != b'20CM':
                raise self.ParseError("not a Need for Speed: Most Wanted save file")
            if True:
                assert False

        self._bChanged = False

    @property
    def path(self):
        return self._path

    @property
    def changed(self):
        return self._bChanged

    def get_alias(self):
        return self._account

    def get_money(self):
        return self._money

    def set_alias(self, alias):
        self._account = alias
        self._bChanged = True

    def set_money(self, money):
        assert 0 <= money <= 2**31 - 1

        self._money = money
        self._bChanged = True

    def save(self):
        if not self._bChanged:
            return

        with open(self._path, "rb+") as inptr:
            assert False

        self._bChanged = False


# https://github.com/popcar2/SaveGameExtractor/blob/master/save_locations.txt
